package deptimpl

import (
	"context"
	"errors"
	"fmt"
	"go-caipu/pkg/services/admin/dept"
	"go-caipu/pkg/services/admin/model"
	"go-caipu/pkg/services/dto"
	"go-caipu/pkg/util"
	"gorm.io/gorm"
)
import "go-caipu/pkg/infra/log"

type store interface {
	Get(ctx context.Context, c dept.GetDeptCommand) (model.SysDept, error)
	Insert(ctx context.Context, sysDept model.SysDept) error
	Update(ctx context.Context, dept model.SysDept) error
	Remove(ctx context.Context, id dept.DeleteDeptCommand) error
	GetDeptList(ctx context.Context, cmd dept.GetDeptTreeListCommand) (deps []model.SysDept, err error)
}

type sqlStore struct {
	db     *gorm.DB
	logger log.Logger
}

func ProvideStore(db *gorm.DB) sqlStore {
	return sqlStore{
		db:     db,
		logger: log.New("dept.store"),
	}
}

// Get 查询部门数据
func (s *sqlStore) Get(ctx context.Context, c dept.GetDeptCommand) (model.SysDept, error) {
	var data model.SysDept
	err := s.db.Model(&data).First(&data, c.Id).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		return data, errors.New(fmt.Sprintf("dept=%d record Not found", c.Id))
	}
	if err != nil {
		s.logger.Log(fmt.Sprintf("dept=%d db  error:%s", c.Id, err.Error()))
		return data, err
	}

	return data, nil
}

// Insert 插入部门数据
func (s *sqlStore) Insert(ctx context.Context, dept model.SysDept) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	//查询当前部门名称是否存在
	var num int64
	err = tx.Model(&dept).Where(" dept_name=?", dept.DeptName).Count(&num).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("check deptname:%s is exists error:%s", dept.DeptName, err.Error()))
		return err
	}
	if num > 0 {
		return errors.New(fmt.Sprintf("deptname:%s record exists", dept.DeptName))
	}
	//插入
	err = tx.Create(&dept).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("insert deptname:%s db  error:%s", dept.DeptName, err.Error()))
		return err
	}
	//构造部门级联数据
	err = updateDeptPath(tx, dept)
	return err
}

func (s *sqlStore) Update(ctx context.Context, dept model.SysDept) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	//查询当前部门名称是否存在
	//var num int64
	//err = tx.Model(&dept).Where(" dept_name=? and  parent_id", dept.DeptName, dept.ParentId).total(&num).Error
	//if err != nil {
	//	s.logger.Log(fmt.Sprintf("update deptname:%s, parent_id:%d  is exists error:%s", dept.DeptName, dept.ParentId, err.Error()))
	//	return err
	//}
	//if num > 0 {
	//	return errors.New(fmt.Sprintf("deptname:%s, parent_id:%d record exists", dept.DeptName, dept.ParentId))
	//}

	//update
	err = tx.Save(&dept).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("update  deptname:%s db  error:%s", dept.DeptName, err.Error()))
		return err
	}
	//重新构造部门级联数据
	return updateDeptPath(tx, dept)
}

// updateDeptPath 重新构造部门数据
func updateDeptPath(tx *gorm.DB, dept model.SysDept) error {
	deptPath := util.Int64toString(dept.DeptId) + "/"
	if dept.ParentId != 0 {
		var deptParent model.SysDept
		tx.First(&deptParent, dept.ParentId)
		deptPath = deptParent.DeptPath + deptPath
	} else {
		deptPath = "/0" + deptPath
	}
	if err := tx.Model(&dept).Update("dept_path", deptPath).Error; err != nil {
		return err
	}
	return nil
}

// Remove 删除部门
func (s *sqlStore) Remove(ctx context.Context, id dept.DeleteDeptCommand) (err error) {
	//判断部门存在员工则不能删除（此处写死表名，后续需要优化）
	var use int64
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	err = tx.Table("sys_user").Where("dept_id IN ? ", id.Ids).Count(&use).Error
	if err != nil {
		return err
	}
	if use > 0 {
		return errors.New("dept exits sysuser")
	}
	var data model.SysDept
	err = tx.Model(&model.SysDept{}).Delete(&data, id.Ids).Error
	if err != nil {
		return err
	}
	return
}

func (s *sqlStore) GetDeptList(ctx context.Context, cmd dept.GetDeptTreeListCommand) (deps []model.SysDept, err error) {
	err = s.db.Model(&model.SysDept{}).Scopes(dto.MakeCondition(cmd)).Preload("CreateUser").Preload("UpdateUser").Find(&deps).Error
	return
}
